package Lono::Fetcher::Client::Epicurious;

use strict;
use warnings;

=head1 NAME

  Lono::Fetcher::Client::Epicurious - a recipe fetcher for epicurious.com

=head1 SYNOPSIS

  my $response = Lono::Fetcher::Client::Epicurious::handle( $html );

=head1 DESCRIPTION

=cut

use base qw( Lono::Fetcher::Client::Base );

use Lono::Fetcher::Response;
use Lono::Recipe::Builder;

use constant SOURCE => 'Epicurious';

my %FIELDS = 
    ('name' => qr{<div\s+id="contentRight">.*?
                  <h1[^>]*>(.*?)</h1>}ismx,
                  
     'description' => qr{<p\s+id="intro_text">(.*?)</p>}ismx,

     'alt_description' => qr{<div\s+id="intro">(.*?)</div>}ismx,
     
     'preparation' => qr{<img\s+src="/images/recipes/recipe_results/preperation_hed.gif"\s+id="prep_hed"\s+class="hdr"\s*/>.*?<div>(.*?)</div>}ismx,
     
     'ingredients' => qr{img\s+src="/images/recipes/recipe_results/ingredients_hed.gif"\s+id="indg_hd"\s+class="hdr"\s*/>\s*<div>\s*(.*?)</div>}ismx,
     
    );

=head1 FUNCTIONS

=over 4

=item new()

Creates a new object.

=cut

sub new {
    my $class = shift;
    my $self = {};
    bless $self, $class;
    return $self;
}

# XXX: so far, all of the extraction here could be done through the DOM...

=item handle( $html )

Given a chunk of HTML, this function tries to parse the content and build a recipe wrapped in a response object.

=cut

sub handle {
    my ( $self, $html, $url ) = @_;

    my $response = Lono::Fetcher::Response->new;
    my $builder = Lono::Recipe::Builder->new;

    # Try to get the name
    my $name = $self->_get_name( $html );
    if ( $name ) {
        $builder->set_name( $name );
    } else {
        $response->log->warning( 'Could not find name.' );
    }

    # Try to get description
    my $description = $self->_get_description( $html );
    if ($description) {
        $builder->set_description($description);
    } else {
        $response->log->warning( 'Could not find description.' );
    }

    # Try to get preparation
    my $preparation = $self->_get_preparation( $html );
    if ( $preparation ) {
        $builder->set_preparation( $preparation );
    } else {
        $response->log->warning( 'Could not find preparation.' );
    }
    
    # Try to get the ingredients
    my @ingredients = $self->_get_ingredients( $html );
    unless (@ingredients) {
        $response->log->warning( 'Could not find ingredients.');
    }
    
    foreach my $raw_ing ( @ingredients ) {
        $builder->add_ingredient( $raw_ing ) ||
            $response->log->warning( 
                "Problem adding ingredient: '$raw_ing'" );
    }

    # Add source and url
    $builder->set_source( SOURCE );
    $builder->set_url( $url );
    
    if ($builder->has_valid_recipe) {
            $response->set_status( $Lono::Fetcher::Response::SUCCESS );
        
        $response->set_recipe( $builder->build_recipe );
    } else {
        # XXX: flesh out the nature of this description more
        $response->log->error( 'Could not build valid recipe.' );
    }
    return $response;
}

sub _get_name {
    my ($self, $html) = @_;
    my $name = $self->_parse_with_regex($FIELDS{'name'}, $html);
    return $name;
}

sub _get_ingredients {
    my ($self, $html) = @_;

    # Try to field out the ingredients
    my $ingredients_blob = $self->_parse_with_regex($FIELDS{'ingredients'}, $html);

    # Remove any links
    # TODO: keep track of links so we can reference other recipes
    $ingredients_blob =~ s{</?a[^>]*>}{}msig;

    my @raw_ingredients = grep length, split(m{\s*<(?:br|p)\s*/?>\s*}msi, $ingredients_blob);



    return @raw_ingredients;
}

sub _get_description {
    my ($self, $html) = @_;
    my $description = $self->_parse_with_regex($FIELDS{'description'}, $html)
        || $self->_parse_with_regex($FIELDS{'alt_description'}, $html);
    
    $description =~ s/<p>/\n/gi;
    
    return $description;
}

sub _get_preparation {
    my ($self, $html) = @_;
    my $preparation = $self->_parse_with_regex($FIELDS{'preparation'}, $html);

    # Remove copyright
    $preparation =~ s{<span\s+class="copyright">.*?</span>}{}ism;

    # Remove source
    $preparation =~ s{<span\s+class="source">.*?</span>}{}ism;

    # Strip remaining HTML
    $preparation =~ s{</?[^>]+>}{}g;

    # Trim excess whitespace at beginning and end
    $preparation =~ s{^[\n\r\s]*}{}sm;
    $preparation =~ s{[\n\r\s]*$}{}s;
    
    # Get rid of extraneous newlines
    $preparation =~ s{[\n\r]{2,}}{\n\n}g;
    
    return $preparation;
}

1;
